package initialize

import (
	"fmt"
	"github.com/APP/config"
	"github.com/APP/global"
	"path/filepath"
	"regexp"

	//"github.com/APP/utils"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
	"path"
	"strings"
	"time"
)

// InitializeZap 初始化 zap 日志
func InitializeZap() {
	cfg := global.APP_CONFIG.Zap

	// 创建日志目录
	if err := os.MkdirAll(cfg.Directory, os.ModePerm); err != nil {
		panic("无法创建日志目录: " + err.Error())
	}

	// 构建完整日志文件路径（每日切割）
	logFile := filepath.Join(cfg.Directory,
		fmt.Sprintf("%s-%s.log", cfg.Prefix, time.Now().Format("2006-01-02")))

	// 设置文件输出器（自动切割）
	fileWriter := zapcore.AddSync(&lumberjack.Logger{
		Filename:   logFile,
		MaxSize:    cfg.MaxSize,
		MaxBackups: cfg.MaxBackups,
		MaxAge:     cfg.MaxAge,
		Compress:   cfg.Compress,
		LocalTime:  true,
	})

	// 日志等级
	level := zapcore.InfoLevel
	_ = level.UnmarshalText([]byte(cfg.Level))

	// 编码器配置
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.CapitalColorLevelEncoder,
		EncodeTime:     zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05"),
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}

	// 选择编码格式
	var encoder zapcore.Encoder
	if cfg.Format == "json" {
		encoder = zapcore.NewJSONEncoder(encoderConfig)
	} else {
		encoder = zapcore.NewConsoleEncoder(encoderConfig)
	}

	// 日志输出目标（文件 + 控制台）
	var cores []zapcore.Core
	cores = append(cores, zapcore.NewCore(encoder, fileWriter, level))

	if cfg.LogInConsole {
		cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), level))
	}

	// 构建 logger
	options := []zap.Option{}
	if cfg.ShowLine {
		options = append(options, zap.AddCaller())
	}

	logger := zap.New(zapcore.NewTee(cores...), options...)

	// 替换全局日志对象
	global.APP_LOG = logger
	zap.ReplaceGlobals(logger)
}

// 创建一个 logger（支持多模块）
func newZapLogger(cfg config.Zap, module string) *zap.Logger {
	// 设置日志级别
	level := zapcore.InfoLevel
	_ = level.UnmarshalText([]byte(cfg.Level))

	// 编码器
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:      "time",
		LevelKey:     "level",
		CallerKey:    "caller",
		MessageKey:   "msg",
		EncodeTime:   zapcore.ISO8601TimeEncoder,
		EncodeLevel:  zapcore.CapitalColorLevelEncoder,
		EncodeCaller: zapcore.ShortCallerEncoder,
	}

	var encoder zapcore.Encoder
	if cfg.Format == "json" {
		encoder = zapcore.NewJSONEncoder(encoderConfig)
	} else {
		encoder = zapcore.NewConsoleEncoder(encoderConfig)
	}

	// 创建切割文件写入器
	writer := getWriter(cfg, module)

	core := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(
		zapcore.AddSync(os.Stdout), zapcore.AddSync(writer),
	), level)

	return zap.New(core, zap.AddCaller())
}

// 返回 rotatelogs 的 writer（按天或按大小切割）
func getWriter(cfg config.Zap, module string) zapcore.WriteSyncer {
	logPath := path.Join(cfg.Directory, module)

	if strings.ToLower(cfg.SplitType) == "daily" {
		rl, err := rotatelogs.New(
			logPath+".%Y-%m-%d.log",
			rotatelogs.WithLinkName(logPath+".log"),
			rotatelogs.WithRotationTime(24*time.Hour),
			rotatelogs.WithMaxAge(time.Duration(cfg.MaxAge)*24*time.Hour),
		)
		if err != nil {
			panic("初始化 rotatelogs 失败: " + err.Error())
		}
		return zapcore.AddSync(rl)
	}

	// fallback: 使用 lumberjack 按大小切割
	return zapcore.AddSync(&lumberjack.Logger{
		Filename:   logPath + ".log",
		MaxSize:    cfg.MaxSize,
		MaxBackups: cfg.MaxBackups,
		MaxAge:     cfg.MaxAge,
		Compress:   cfg.Compress,
	})
}

func MoveOldLogsToDateFolder(logDir string) {
	for {
		files, _ := os.ReadDir(logDir)
		today := time.Now().Format("2006-01-02")
		targetDir := filepath.Join(logDir, today)

		// 创建日期文件夹
		os.MkdirAll(targetDir, os.ModePerm)

		for _, file := range files {
			name := file.Name()
			if strings.Contains(name, today) || !strings.Contains(name, ".log") {
				continue
			}
			// 匹配类似 http.2025-08-01.log
			if matches := regexp.MustCompile(`\.(\d{4}-\d{2}-\d{2})\.log$`).FindStringSubmatch(name); len(matches) > 1 {
				dateStr := matches[1]
				destDir := filepath.Join(logDir, dateStr)
				os.MkdirAll(destDir, os.ModePerm)

				src := filepath.Join(logDir, name)
				dst := filepath.Join(destDir, name)

				_ = os.Rename(src, dst) // 移动文件
			}
		}
		time.Sleep(1 * time.Hour) // 每小时检查一次
	}
}
